<?php
   include("TableDefDAO.php");

   function generateDaoAndValueObject ($table, $class)
   {
	global $dbhost, $dbschema, $dbuser, $dbpass;

    if(strlen($table) > 0 && strlen($class) > 0) {
        $dao = new TableDefDAO($dbhost, $dbschema, $dbuser, $dbpass);
        $volist = $dao->describe($table);
        echo mysql_error();
        $dao->close();

        // find the primary key field
        $pk_field = "id";
        foreach($volist as $vo) {
            if($vo->isPK()) {
                $pk_field = $vo->field;
            }
        }

        $buf = "<?php\n";

        $buf .= "require_once (\"BaseDAO.php\");\n\n";

        $buf .= "// $class Value Object\n";
        $buf .= "class " . $class . " extends BaseVO {\n";
        foreach($volist as $vo) {
            $buf .= "\tvar \x24" . $vo->field . ";\n";
        }
        $buf .= "\n";
        $buf .= "\t// create a new VO\n";
        $buf .= "\tfunction " . $class . "(\n";
        $tmp = "";
        foreach($volist as $vo) {
            if($vo->isNumber()) {
                $tmp .="\t\t\x24" . $vo->field . "= 0,\n";
            } else {
                $tmp .="\t\t\x24" . $vo->field . "= \"\",\n";
            }
        }
        //clear off the last ",\n"
        $tmp = substr($tmp, 0, strlen($tmp)-2);
        $buf .= $tmp . "\n";
        $buf .= "\t) {\n";

        foreach($volist as $vo) {
            $buf .= "\t\t\x24this->" . $vo->field . " = \x24" . $vo->field . ";\n";
        }
        $buf .= "\t}\n\n";

        $buf .= "\t// compare to another VO\n";
        $buf .= "\tfunction equals(\x24vo) {\n";
        $buf .= "\t\treturn ";
        $tmp = "";
        foreach($volist as $vo) {
            $tmp .= "\x24this->" . $vo->field . " == \x24vo->" . $vo->field . " &&\n\t\t\t";
        }
        //clear off the last "&&\n"
        $tmp = substr($tmp, 0, strlen($tmp)-7);
        // add a ";\n"
        $tmp .= ";\n";
        $buf .= $tmp;
        $buf .= "\t}\n";

        $buf .= "\t// copies another VO\n";
        $buf .= "\tfunction copy(\x24vo) {\n";
        foreach($volist as $vo) {
            $buf .= "\t\t\x24this->" . $vo->field . " = \x24vo->" . $vo->field . ";\n";
        }
        $buf .= "\t}\n\n";

        $buf .= "\t// output as a string\n";
        $buf .= "\tfunction toString() {\n";
        $buf .= "\t\treturn ";
        $tmp = "";
        foreach($volist as $vo) {
            $tmp .= "\x24this->" . $vo->field . " . \",\" . ";
        }
        $tmp = substr($tmp, 0, strlen($tmp)-9);
        $tmp .= ";\n";
        $buf .= $tmp;
        $buf .= "\t}\n\n";

        $buf .= "\t// output as XML node\n";
        $buf .= "\tfunction toXML() {\n";
        $buf .= "\t\treturn \"<row>\\n\" .\n";
        $tmp = "";
        foreach($volist as $vo) {
            $tmp .= "\t\t\"<" . $vo->field . ">\x24this->" . $vo->field . "</" . $vo->field . ">\\n\" .\n";
        }
        $buf .= $tmp;
        $buf .= "\t\t\"</row>\\n\";\n";
        $buf .= "\t}\n\n";

        $buf .= "\t// read from an html form\n";
        $buf .= "\tfunction readForm(\x24prefix=\"\") {\n";
        foreach($volist as $vo) {
            if($vo->isNumber()) {
                if (strpos(strrev($vo->field), "di_") === 0)
                {
                	$buf .= "\t\t\x24this->" . $vo->field . " = \x24this->formHelper(\x24prefix . \"" . $vo->field . "\", 'null');\n";
                }
                else
                {
                	$buf .= "\t\t\x24this->" . $vo->field . " = \x24this->formHelper(\x24prefix . \"" . $vo->field . "\", 0);\n";
                }
            } else {
                $buf .= "\t\t\x24this->" . $vo->field . " = \x24this->formHelper(\x24prefix . \"" . $vo->field . "\", \"\");\n";
            }
        }
        $buf .= "\t}\n\n";

        $buf .= "\t// read from the query string\n";
        $buf .= "\tfunction readQuery(\x24prefix=\"\") {\n";
        foreach($volist as $vo) {
            if($vo->isNumber()) {
                if (strpos(strrev($vo->field), "di_") === 0)
                {
                	$buf .= "\t\t\x24this->" . $vo->field . " = \x24this->queryHelper(\x24prefix . \"" . $vo->field . "\", 'null');\n";
                }
                else
                {
   	                $buf .= "\t\t\x24this->" . $vo->field . " = \x24this->queryHelper(\x24prefix . \"" . $vo->field . "\", 0);\n";
                }
            } else {
                $buf .= "\t\t\x24this->" . $vo->field . " = \x24this->queryHelper(\x24prefix . \"" . $vo->field . "\", \"\");\n";
            }
        }
        $buf .= "\t}\n\n";

        $buf .= "\t// extra functions here\n";
        $buf .= "\tfunction getPK() {\n";
        foreach($volist as $vo) {
            if($vo->iskey == "PRI") {
                $buf .= "\t\treturn \x24this->" . $vo->field . ";\n";
            }
        }
        $buf .= "\t}\n";


        $buf .= "}\n\n";


        $buf .= "// $class Data Access Object\n";
        $buf .= "class " . $class . "DAO extends BaseDAO {\n";
        $buf .= "\tvar \x24SQL_SELECT = \"SELECT * FROM `$table` \";\n";
        $buf .= "\tvar \x24SQL_COUNT = \"SELECT count(*) AS cnt FROM `$table` \";\n";
        $buf .= "\t// insert with no value for an auto_increment field.\n";
        $buf .= "\tvar \x24SQL_INSERT = \"INSERT INTO `$table` (";
        $tmp = "";
        foreach($volist as $vo) {
            if ($vo->extra != "auto_increment") {
                $tmp .= $vo->field . ",";
            }
        }
        $buf .= substr($tmp, 0, strlen($tmp)-1);
        $buf .= ") VALUES (";
        $cnt = 65;
        $tmp = "";
        foreach($volist as $vo) {
            // do not insert auto_increment type fields.
            if ($vo->extra != "auto_increment") {
                // letter A to Z... any table with more than 26 fields
                // is not normalized and the DBA should be killed.
                if($vo->isNumber()) {
                    $tmp .= "%" . chr($cnt++) . ",";
                } else if ($vo->isPassword()) {
					$tmp .= "MD5('%" . chr($cnt++) . "'),";
            	} else if ($vo->isDate()) {
					$tmp .= "'%" . chr($cnt++) . "',";
            	} else {
                    $tmp .= "'%" . chr($cnt++) . "',";
                }
                if($cnt > 90 && $cnt < 97) { $cnt=97 ;}
            }
        }
        $buf .= substr($tmp, 0, strlen($tmp)-1);
        $buf .= ")\";\n";

        $buf .= "\tvar \x24SQL_UPDATE = \"UPDATE `$table` SET \";\n";
        $buf .= "\tvar \x24SQL_DELETE = \"DELETE FROM `$table` ";
        $tmp = "";
        foreach($volist as $vo) {
            if($vo->isPK()) {
                if($vo->isNumber()) {
                    $tmp = "WHERE " . $vo->field . "=%A\";\n";
                } else {
                    $tmp = "WHERE " . $vo->field . "='%A'\";\n";
                }
            }
        }
        $buf .= $tmp . "\n";

        $buf .= "\t// default constructor\n";
        $buf .= "\tfunction " . $class . "DAO(\x24dbserver=\"\", \x24dbname=\"\", \x24dbuser=\"\", \x24dbpass=\"\") {\n";
        $buf .= "\t\t// calls the parent constructor which\n";
        $buf .= "\t\t// makes the database connection.\n";
        $buf .= "\t\tparent::BaseDAO(\x24dbserver, \x24dbname, \x24dbuser, \x24dbpass);\n";
        $buf .= "\t}\n\n";

        $buf .= "\t// returns a single " . $class . " obeject\n";
        $buf .= "\tfunction get(\x24" . $pk_field . ") {    \n";
        $buf .= "\t\x24this->sql = \x24this->SQL_SELECT . \"WHERE (" . $pk_field . "='\" . \x24this->safeEscapeStr(\x24" . $pk_field . ") . \"')\";\n";
        $buf .= "\t\t\x24this->exec(\x24this->sql);\n";
        $buf .= "\t\tif(\x24this->numRows() > 0 ) {\n";
        $buf .= "\t\t\t\x24row = \x24this->getObject();\n";
        $buf .= "\t\t\t\x24vo = new " . $class . "(\n";
        $tmp = "";
        foreach($volist as $vo) {
            $tmp .= "\t\t\t\t\x24row->" . $vo->field . ", \n";
        }
        $buf .= substr($tmp, 0, strlen($tmp)-3);
        $buf .= "\n\t\t\t);\n";
        $buf .= "\t\t\treturn \x24vo;\n";
        $buf .= "\t\t} else {\n";
        $buf .= "\t\t\treturn null;    \n";
        $buf .= "\t\t}\n";
        $buf .= "\t}\n\n";

        $buf .= "\t// returns an array of " . $class . " objects\n";
        $buf .= "\t// given a complete SQL query \n";
        $buf .= "\t// The SQL Query needs to be safely escaped by the caller!\n";
        $buf .= "\tfunction findBySQL(\x24sql) {\n";
        $buf .= "\t\t\x24voList = array();\n";
        $buf .= "\t\t\x24this->sql = \x24sql;\n";
        $buf .= "\t\t\x24this->exec(\x24this->sql);\n";
        $buf .= "\t\twhile(\x24row = \x24this->getObject()) {\n";
        $buf .= "\t\t\t\x24vo = new " . $class . "(\n";
        $tmp = "";
        foreach($volist as $vo) {
            $tmp .= "\t\t\t\t\x24row->" . $vo->field . ", \n";
        }
        $buf .= substr($tmp, 0, strlen($tmp)-3);
        $buf .= "\n\t\t\t);\n";
        $buf .= "\t\t\tarray_push(\x24voList, \x24vo);\n";
        $buf .= "\t\t}\n";
        $buf .= "\t\treturn \x24voList;\n";
        $buf .= "\t}\n\n";

        $buf .= "\t// returns an array of " . $class . " objects\n";
        $buf .= "\t// value for \x24where is some thing like \"(xxx = 'abc') AND (zzz='123')\"\n";
        $buf .= "\t// value for \x24order_by is a comma separated list of columns \"company, name\"\n";
        $buf .= "\t// the where and order clauses should be safely escaped by the caller!\n";
        $buf .= "\tfunction findWhere(\x24where = \"\", \x24orderby = \"\") {\n";
        $buf .= "\t\t\x24this->sql = \x24this->SQL_SELECT;\n";
        $buf .= "\t\t\x24voList = array();\n";
        $buf .= "\t\tif(strlen(\x24where) > 0 ) {\n";
        $buf .= "\t\t\t\x24where = \"WHERE (\" . \x24where . \") \";\n";
        $buf .= "\t\t}\n";
        $buf .= "\t\tif(strlen(\x24orderby) > 0) {\n";
        $buf .= "\t\t\t\x24orderby = \"ORDER BY \" . \x24orderby;\n";
        $buf .= "\t\t} else {\n";
        $buf .= "\t\t\t\x24orderby = \"ORDER BY 1\";\n";
        $buf .= "\t\t}\n";
        $buf .= "\t\t\x24this->sql .= \x24where . \" \" . \x24orderby;\n";
        $buf .= "\t\t\x24this->exec(\x24this->sql);\n";
        $buf .= "\t\twhile(\x24row = \x24this->getObject()) {\n";
        $buf .= "\t\t\t\x24vo = new " . $class . "(\n";
        $tmp = "";
        foreach($volist as $vo) {
            $tmp .= "\t\t\t\t\x24row->" . $vo->field . ", \n";
        }
        $buf .= substr($tmp, 0, strlen($tmp)-3);
        $buf .= "\n\t\t\t);\n";
        $buf .= "\t\t\tarray_push(\x24voList, \x24vo);\n";
        $buf .= "\t\t}\n";
        $buf .= "\t\treturn \x24voList;\n";
        $buf .= "\t}\n\n";

        $buf .= "\t// returns an array of " . $class . " objects based on the example\n";
        $buf .= "\tfunction findExample(\x24example, \x24orderby=\"\") {\n";
        $buf .= "\t\t\x24this->sql = \x24this->SQL_SELECT;\n";
        $buf .= "\t\t\x24voList = array();\n";
        $buf .= "\t\t\x24where = \"\";\n\n";
        $buf .= "\t\t\x24tmp = \"\";\n";
        $tmp = "";
        foreach($volist as $vo) {
            if($vo->isNumber()) {
                $tmp .="\t\tif(\x24example->" . $vo->field . " != 0) \x24tmp .= \"" . $vo->field . " = \" . \x24this->safeEscapeStr(\x24example->" . $vo->field .") . \" and \";\n";
            } else if ($vo->isDate()) {
            	$tmp .="\t\tif(strlen(\x24example->" . $vo->field . ") > 0) \x24tmp .= \"" . $vo->field . " = DATE('\" . \x24this->safeEscapeStr(\x24example->" . $vo->field .") . \"') and \";\n";
            } else if ($vo->isPassword()) {
            	$tmp .="\t\tif(strlen(\x24example->" . $vo->field . ") > 0) \x24tmp .= \"" . $vo->field . " = MD5('\" . \x24this->safeEscapeStr(\x24example->" . $vo->field .") . \"') and \";\n";
            } else {
                $tmp .="\t\tif(strlen(\x24example->" . $vo->field . ") > 0) \x24tmp .= \"" . $vo->field . " like '%\" . \x24this->safeEscapeStr(\x24example->" . $vo->field .") . \"%' and \";\n";
            }
        }
        $buf .= $tmp;
        $buf .= "\t\tif (\x24tmp != \"\") {\x24where = \"WHERE (\" . substr(\x24tmp, 0, strlen(\x24tmp)-4) . \") \";}\n";
        $buf .= "\t\tif(strlen(\x24orderby) > 0) {\n";
        $buf .= "\t\t\t\x24orderby = \"ORDER BY \" . \x24orderby;\n";
        $buf .= "\t\t} else {\n";
        $buf .= "\t\t\t\x24orderby = \"ORDER BY 1\";\n";
        $buf .= "\t\t}\n";
        $buf .= "\t\t\x24this->sql .= \x24where . \" \" . \x24orderby;\n";
        $buf .= "\t\t\x24this->exec(\x24this->sql);\n";
        $buf .= "\t\twhile(\x24row = \x24this->getObject()) {\n";
        $buf .= "\t\t\t\x24vo = new " . $class . "(\n";
        $tmp = "";
        foreach($volist as $vo) {
            $tmp .= "\t\t\t\t\x24row->" . $vo->field . ", \n";
        }
        $buf .= substr($tmp, 0, strlen($tmp)-3);
        $buf .= "\n\t\t\t);\n";
        $buf .= "\t\t\tarray_push(\x24voList, \x24vo);\n";
        $buf .= "\t\t}\n";
        $buf .= "\t\treturn \x24voList;\n";
        $buf .= "\t}\n\n";

        $buf .= "\t// insert a record from a vo\n";
        $buf .= "\tfunction insert(&\x24vo) {\n";
        $buf .= "\t\t\x24this->sql = \x24this->SQL_INSERT;\n";
        $tmp = "";
        $cnt = 65;
        foreach($volist as $vo) {
            if ($vo->extra != "auto_increment") {
                $tmp .="\t\t\x24this->sql = str_replace(\"%" . chr($cnt++) . "\", \x24this->safeEscapeStr(\x24vo->" . $vo->field . "), \x24this->sql);\n";
                if($cnt > 90) { $cnt=97 ;}
            }
        }
        $buf .= $tmp;
        $buf .= "\n\t\t\x24this->exec(\x24this->sql);";
        $buf .= "\n\t\t\x24vo->" . $pk_field . " = \x24this->lastOID();\n";
        $buf .= "\t\treturn \x24this->affectedRows();\n";
        $buf .= "\t}\n\n";

        $buf .= "\t// update a record from a vo\n";
        $buf .= "\tfunction update(\x24vo) {\n";
        $buf .= "\t\t\x24this->sql = \x24this->SQL_UPDATE;\n";
        $tmp = "";
        foreach($volist as $vo) {
            if (!$vo->isPK()) {
            	if ($vo->isNumber()) {
            		$tmp .= "\t\t\x24this->sql .= \"" . $vo->field . " = \" . \x24this->safeEscapeStr(\x24vo->" . $vo->field . ") . \", \";\n";
            	} else if ($vo->isPassword()) {
            		$tmp .= "\t\tif(strlen(\x24vo->" . $vo->field . ") > 0 )\n";
            		$tmp .= "\t\t\t\x24this->sql .= \"" . $vo->field . " = MD5('\" . \x24this->safeEscapeStr(\x24vo->" . $vo->field . ") . \"'), \";\n";
            	} else if ($vo->isDate()){
            		$tmp .= "\t\t\x24this->sql .= \"" . $vo->field . " = '\" . \x24this->safeEscapeStr(\x24vo->" . $vo->field . ") . \"', \";\n";
            	} else {
            		$tmp .= "\t\t\x24this->sql .= \"" . $vo->field . " = '\" . \x24this->safeEscapeStr(\x24vo->" . $vo->field . ") . \"', \";\n";
            	}
            }
        }
        $buf .= substr($tmp, 0, strlen($tmp)-5) . " \";\n";
        $buf .= "\n\t\t\x24this->sql .= \"WHERE ". $pk_field . "=\" . \x24this->safeEscapeStr(\x24vo->". $pk_field . ");\n";

        $buf .= "\n\t\t\x24this->exec(\x24this->sql);\n";

        $buf .= "\t\treturn \x24this->affectedRows();\n";
        $buf .= "\t}\n\n";

	$buf .= "\t//save an object to the databse (update or insert as needed)\n";
        $buf .= "\tfunction save(&\x24vo) {\n";
        $buf .= "\t\tif (\x24vo->" . $pk_field . " <= 0)\n";
	$buf .= "\t\t\treturn \x24this->insert(\x24vo);\n";
	$buf .= "\t\telse\n";
	$buf .= "\t\t\treturn \x24this->update(\x24vo);\n";
	$buf .= "\t}\n\n";

        $buf .= "\t// delete a record from a vo\n";
        $buf .= "\tfunction delete(\x24vo) {\n";
        $buf .= "\t\t\x24this->sql = \x24this->SQL_DELETE;\n";
        $buf .= "\t\t\x24this->sql = str_replace(\"%A\", \x24this->safeEscapeStr(\x24vo->". $pk_field . "), \x24this->sql);\n";

        $buf .= "\t\t\x24this->exec(\x24this->sql);\n";

        $buf .= "\t\treturn \x24this->affectedRows();\n";
        $buf .= "\t}\n\n";

        $buf .= "\t// delete a record from a vo\n";
        $buf .= "\tfunction deleteWhere(\x24where) {\n";
        $buf .= "\t\t\x24this->sql = \"DELETE FROM `$table` WHERE \";\n";
        $buf .= "\t\t\x24this->sql .= \x24where;\n";

        $buf .= "\t\t\x24this->exec(\x24this->sql);\n";

        $buf .= "\t\treturn \x24this->affectedRows();\n";
        $buf .= "\t}\n\n";

        $buf .= "}\n\n";

	return $buf;
    }
  }
?>
